package cn.duckerkj.util.safeutil;
import java.security.spec.KeySpec;  
import javax.crypto.Cipher;  
import javax.crypto.SecretKey;  
import javax.crypto.SecretKeyFactory;  
import javax.crypto.spec.DESKeySpec;  
import javax.crypto.spec.DESedeKeySpec;

public class UnionDes {

    static String DES = "DES/ECB/NoPadding";  
    static String TriDes = "DESede/ECB/NoPadding";  
    
    /**
     * 十六进制字符串转二进制
     * @param str 十六进制串
     * @return
     */
    public static byte[] hex2byte(String str) { //字符串转二进制
        int len = str.length();
        String stmp = null;
        byte bt[] = new byte[len / 2];
        for (int n = 0; n < len / 2; n++) {
            stmp = str.substring(n * 2, n * 2 + 2);
            bt[n] = (byte) (java.lang.Integer.parseInt(stmp, 16));
        }
        return bt;
    }
    
    /**
     * 二进制转十六进制字符串
     * @param b
     * @return
     */
    public static String byte2hex(byte[] b) { //二行制转字符串
        String hs = "";
        String stmp = "";
        for (int n = 0; n < b.length; n++) {
            stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
            if (stmp.length() == 1) {
                hs = hs + "0" + stmp;
            } else {
                hs = hs + stmp;
            }
            if (n < b.length - 1) {
                hs = hs + "";
            }
        }
        return hs.toUpperCase();
    }
    
    /**
     * des加密
     * @param key 密钥
     * @param data 明文数据 16进制且长度为16的整数倍
     * @return  密文数据
     */
    public static byte[] UnionDesEncrypt(byte key[], byte data[]) {  
  
        try {  
            KeySpec ks = new DESKeySpec(key);  
            SecretKeyFactory kf = SecretKeyFactory.getInstance("DES");  
            SecretKey ky = kf.generateSecret(ks);  
  
            Cipher c = Cipher.getInstance(DES);  
            c.init(Cipher.ENCRYPT_MODE, ky);  
            return c.doFinal(data);  
        } catch (Exception e) {  
            e.printStackTrace();  
            return null;  
        }  
    }  
  
    /**
     * des解密
     * @param key 密钥
     * @param data 密文数据 16进制且长度为16的整数倍
     * @return 明文数据
     */
    public static byte[] UnionDesDecrypt(byte key[], byte data[]) {  
  
        try {  
            KeySpec ks = new DESKeySpec(key);  
            SecretKeyFactory kf = SecretKeyFactory.getInstance("DES");  
            SecretKey ky = kf.generateSecret(ks);  
  
            Cipher c = Cipher.getInstance(DES);  
            c.init(Cipher.DECRYPT_MODE, ky);  
            return c.doFinal(data);  
        } catch (Exception e) {  
            e.printStackTrace();  
            return null;  
        }  
    }  
    
    /**
     * 3des加密
     * @param key 密钥
     * @param data 明文数据 16进制且长度为16的整数倍
     * @return  密文数据
     */
    public static byte[] Union3DesEncrypt(byte key[], byte data[]) {  
        try {  
            byte[] k = new byte[24];  
  
            int len = data.length;  
            if(data.length % 8 != 0){  
                len = data.length - data.length % 8 + 8;  
            }  
            byte [] needData = null;  
            if(len != 0)  
                needData = new byte[len];  
              
            for(int i = 0 ; i< len ; i++){  
                needData[i] = 0x00;  
            }  
              
            System.arraycopy(data, 0, needData, 0, data.length);  
              
            if (key.length == 16) {  
                System.arraycopy(key, 0, k, 0, key.length);  
                System.arraycopy(key, 0, k, 16, 8);  
            } else {  
                System.arraycopy(key, 0, k, 0, 24);  
            }  
  
            KeySpec ks = new DESedeKeySpec(k);  
            SecretKeyFactory kf = SecretKeyFactory.getInstance("DESede");  
            SecretKey ky = kf.generateSecret(ks);  
  
            Cipher c = Cipher.getInstance(TriDes);  
            c.init(Cipher.ENCRYPT_MODE, ky);  
            return c.doFinal(needData);  
        } catch (Exception e) {  
            e.printStackTrace();  
            return null;  
        }  
  
    }  
    
    /**
     * 3des解密
     * @param key 密钥
     * @param data 密文数据 16进制且长度为16的整数倍
     * @return   明文数据
     */
    public static byte[] Union3DesDecrypt(byte key[], byte data[]) {  
        try {  
            byte[] k = new byte[24];  
  
            int len = data.length;  
            if(data.length % 8 != 0){  
                len = data.length - data.length % 8 + 8;  
            }  
            byte [] needData = null;  
            if(len != 0)  
                needData = new byte[len];  
              
            for(int i = 0 ; i< len ; i++){  
                needData[i] = 0x00;  
            }  
              
            System.arraycopy(data, 0, needData, 0, data.length);  
              
            if (key.length == 16) {  
                System.arraycopy(key, 0, k, 0, key.length);  
                System.arraycopy(key, 0, k, 16, 8);  
            } else {  
                System.arraycopy(key, 0, k, 0, 24);  
            }  
            KeySpec ks = new DESedeKeySpec(k);  
            SecretKeyFactory kf = SecretKeyFactory.getInstance("DESede");  
            SecretKey ky = kf.generateSecret(ks);  
  
            Cipher c = Cipher.getInstance(TriDes);  
            c.init(Cipher.DECRYPT_MODE, ky);  
            return c.doFinal(needData);  
        } catch (Exception e) {  
            e.printStackTrace();  
            return null;  
        }  
  
    }  
    /**
     * 数据解密
     * @param key 密钥 支持单倍和多倍密钥
     * @param data 密文数据 16进制且长度为16的整数倍
     * @return 明文数据
     */
    public static String UnionDecryptData(String key, String data)
    {
     if((key.length() != 16) && (key.length() != 32) && (key.length() != 48))
     {
      return(null);
     }
     if(data.length()%16 != 0)
     {
      return"";
     }
     int lenOfKey = 0;
     lenOfKey = key.length();
     String strEncrypt = "";
     byte sourData[] = hex2byte(data);
     switch(lenOfKey)
     {
     case 16:
      byte deskey8[] = hex2byte(key);      
      byte encrypt[] = UnionDesDecrypt(deskey8, sourData);
      strEncrypt = byte2hex(encrypt);
      break;
     case 32:
     case 48:
      String newkey1 = "";
      if(lenOfKey == 32)
      {
       String newkey = key.substring(0, 16);
       newkey1 = key+newkey;
      }else
      {
       newkey1 = key;
      }
      byte deskey24[] = hex2byte(newkey1);
      byte desEncrypt[] = Union3DesDecrypt(deskey24, sourData);
      strEncrypt = byte2hex(desEncrypt);
     }
     return strEncrypt;
    }
    
    /**
     * 加密数据
     * @param key 密钥 16进制且长度为16的整数倍
     * @param data 明文数据 16进制且长度为16的整数倍
     * @return  密文数据
     */
 public static String UnionEncryptData(String key, String data)
    {
     if((key.length() != 16) && (key.length() != 32) && (key.length() != 48))
     {
      return(null);
     }
     if(data.length()%16 != 0)
     {
      return"";
     }
     int lenOfKey = 0;
     lenOfKey = key.length();
     String strEncrypt = "";
     byte sourData[] = hex2byte(data);
     switch(lenOfKey)
     {
     case 16:
      byte deskey8[] = hex2byte(key);      
      byte encrypt[] = UnionDesEncrypt(deskey8, sourData);
      strEncrypt = byte2hex(encrypt);
      break;
     case 32:
     case 48:
      String newkey1 = "";
      if(lenOfKey == 32)
      {
       String newkey = key.substring(0, 16);
       newkey1 = key+newkey;
      }else
      {
       newkey1 = key;
      }
      byte deskey24[] = hex2byte(newkey1);
      byte desEncrypt[] = Union3DesEncrypt(deskey24, sourData);
      strEncrypt = byte2hex(desEncrypt);
      break;
     }
     return strEncrypt;
    }
  
    public static void main(String[] args) {  
     String key =  "11111111111111111111111111111111";
     String data = "00000000000000000000000000000000";
     
     String encData = UnionEncryptData(key,data);
     System.out.println("encData = "+encData);
     
     String sourData = UnionDecryptData(key,encData);
     System.out.println("sourData = "+sourData);
    }  
}